package com.wanho.qz103.hrsaas.commons.util;

import com.wanho.qz103.hrsaas.commons.annontations.Component;
import com.wanho.qz103.hrsaas.commons.exception.DataAccessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.apache.commons.lang3.ArrayUtils;

import java.sql.SQLException;
import java.util.List;

/**
 * 对数据库 基本操作
 */
@Slf4j
@Component
public final class JDBCTemplate {
    /**dbutils apache 提供jdbc 工具封装类*/
    private QueryRunner queryRunner = new QueryRunner() ;
    /**
     * 实现 数据 DML 操作： insert，update ，delete
     * @param DML  sql 语句
     * @param params ？占位符
     * @return  true 操作成功  false 操作失败
     * @throws DataAccessException
     */
    public boolean update(final String DML,final Object ... params) throws DataAccessException{
        try {
            return  queryRunner.update(JDBCUtil.getConnection(),DML,params)>0 ;
        } catch (SQLException e) {
            e.printStackTrace();
            log.debug("执行SQL异常："+DML+",参数:"+ ArrayUtils.toString(params));
            throw new DataAccessException(e.getMessage()) ;
        }
    }

    /**
     * 查询  返回 一条数据 或 0
     * @param DQL   查询SQL语句 返回一行或0行
     * @param pojoCls  查询结果集封装的实体类 pojos  根据结果集的列名 进行反射自动映射到该同名属性中
     * @param params   ？ 占位符
     * @param <T>      封装的实体类 类型
     * @return         封装的实体类的 实例
     * @throws DataAccessException  执行SQL异常！！！
     */
    public <T> T queryObject(final String DQL,final Class<?> pojoCls,final  Object ... params) throws DataAccessException{
        try {
            return (T) queryRunner.query(JDBCUtil.getConnection(),DQL,new BeanHandler<>(pojoCls),params);
        } catch (SQLException e) {
            e.printStackTrace();
            log.debug("执行SQL异常："+DQL+",参数:"+ ArrayUtils.toString(params));
            throw new DataAccessException(e.getMessage()) ;
        }
    }

    /**
     * 查询  返回 多条数据 或 0
     * @param DQL   查询SQL语句 返回多行或0行
     * @param pojoCls  查询结果集封装的实体类 pojos  根据结果集的列名 进行反射自动映射到该同名属性中
     * @param params   ？ 占位符
     * @return         封装的实体类的对象数组
     * @throws DataAccessException  执行SQL异常！！！
     */
    public List queryList(final String DQL, final Class<?> pojoCls, final  Object ... params) throws DataAccessException{
        try {
            return queryRunner.query(JDBCUtil.getConnection(),DQL,new BeanListHandler<>(pojoCls),params) ;
        } catch (SQLException e) {
            e.printStackTrace();
            log.debug("执行SQL异常："+DQL+",参数:"+ ArrayUtils.toString(params));
            throw new DataAccessException(e.getMessage()) ;
        }
    }

    /**
     * 统计 满足条件的记录数
     * @param DQL 执行统计的SQL语句 返回 单行单列
     * @param params  ？ 占位符的值
     * @return        统计的行数
     * @throws DataAccessException  执行count统计的sql异常！！！
     */
    public long queryLong(final String DQL,final  Object ... params) throws DataAccessException{
        try {
            return  queryRunner.query(JDBCUtil.getConnection(),DQL,new ScalarHandler<>(),params) ;
        } catch (SQLException e) {
            e.printStackTrace();
            log.debug("执行SQL异常："+DQL+",参数:"+ ArrayUtils.toString(params));
            throw new DataAccessException(e.getMessage()) ;
        }
    }

    /**
     * 批量插入数据
     * @param DML  执行新增一条记录的SQL
     * @param params  ？ 多行多列的二维数组
     * @return        true 成功  false失败
     * @throws DataAccessException
     */
    public boolean insertBatch(final String DML,final Object[] ... params) throws DataAccessException{
        try {
             // 无需使用其结果集 故面向异常编程   逻辑上：返回新增批处理的数据id pk 数组
             queryRunner.insertBatch(JDBCUtil.getConnection(),DML,new ScalarHandler<>(),params);
             // 如果不出现异常：返回true
             return true ;
        } catch (SQLException e) {
            e.printStackTrace();
            log.debug("执行SQL异常："+DML+",参数:"+ ArrayUtils.toString(params));
            throw new DataAccessException(e.getMessage()) ;
        }
    }
}
